#import "GuaziAppDelegate.h"
#import "DirectMessage.h"
#import "DBConnection.h"
#import "Followee.h"
#import "REString.h"
#import "StringUtil.h"
#import "Status.h"
#import "JSON.h"

@interface DirectMessage(Private)
- (void)insertDB;
@end

@implementation DirectMessage

@synthesize recipient;
@synthesize senderId;
@synthesize recipientId;
@synthesize senderScreenName;
@synthesize recipientScreenName;

@synthesize appendCode;
@synthesize appendParams;
@synthesize appendResult;


- (void)dealloc
{
    [senderScreenName release];
    [recipientScreenName release];
    [appendCode release];
    [appendParams release];
    [appendResult release];
  	[super dealloc];
}



- (DirectMessage*)initWithJsonDictionary:(NSDictionary*)dic
{
	self = [super init];
    
	tweetId             = [[dic objectForKey:@"id"] longLongValue];
    stringOfCreatedAt   = [dic objectForKey:@"created_at"];
    if ((id)stringOfCreatedAt == [NSNull null]) {
        stringOfCreatedAt = @"";
    }
    
    NSString *tweet = [dic objectForKey:@"text"];

    if ((id)tweet == [NSNull null]) {
        text = @"";
    }
    else {
        tweet = [[tweet unescapeHTML] stringByReplacingOccurrencesOfString:@"\n" withString:@" "];
        text  = [[tweet stringByReplacingOccurrencesOfString:@"\r" withString:@" "] retain];
    }
	
	NSDictionary* senderDic = [dic objectForKey:@"sender"];
	if (senderDic) {
        user = [User userWithJsonDictionary:senderDic];
    }
    NSDictionary* recipientDic = [dic objectForKey:@"recipienter"];
	if (recipientDic) {
        recipient = [User userWithJsonDictionary:recipientDic];
    }
	
    senderId = user.userId;
    recipientId = recipient.userId;

	if ( user != nil ) self.senderScreenName = user.screenName;
	if (recipient != nil) self.recipientScreenName = recipient.screenName;
    if (senderScreenName == nil ) {
        self.senderScreenName = @"";
    }
    if (recipientScreenName == nil ) {
        self.recipientScreenName = @"";
    }
    
    [self updateAttribute];
    unread = true;
    
    id i = [dic objectForKey:@"appendCode"];
    if ( i == nil || i == [NSNull null] ) {
        self.appendCode = @"";
    }
    else {
        self.appendCode = i;
    }
    
    i = [dic objectForKey:@"appendResult"];
    if ( i == nil || i == [NSNull null] ) {
        self.appendResult = @"";
    }
    else {
        self.appendResult = i;
    }
    
    i = [dic objectForKey:@"appendParam"];
    NSLog(@"params=%@", [dic objectForKey:@"appendParam"] );
    if ( i == nil || i == [NSNull null] ) {
        self.appendParams = @"";
    }
    else {
        self.appendParams = i;
    }

	return self;
}


+ (DirectMessage*)messageWithJsonDictionary:(NSDictionary*)dic
{
	return [[[DirectMessage alloc] initWithJsonDictionary:dic] autorelease];
}


- (id)copyWithZone:(NSZone *)zone
{
    DirectMessage *dist = [super copyWithZone:zone];
    
	dist.recipient  = recipient;
    dist.senderScreenName      = senderScreenName;
    dist.recipientScreenName   = recipientScreenName;
    
    dist.appendCode = appendCode;
    dist.appendParams = appendParams;
    dist.appendResult = appendResult;
    
    return dist;
}


- (void)updateAttribute
{
    [super updateAttribute];  
    [self calcTextBounds:CELL_WIDTH - INDICATOR_WIDTH];
}


+ (DirectMessage*)initWithStatement:(Statement*)stmt
{
    // sqlite3 statement should be:
    //  SELECT id, text, created_at FROM messsages WHERE sender_id = ?
    //
    DirectMessage *dm       = [[DirectMessage alloc] init];
   
    dm.messageId            = [stmt getInt64:0];
    dm.senderId             = [stmt getInt64:1];
    dm.recipientId          = [stmt getInt64:2];
    dm.text                 = [stmt getString:3];
    dm.createdAt            = [stmt getInt32:4];
    dm.senderScreenName     = [stmt getString:5];
    dm.recipientScreenName  = [stmt getString:6];
    dm.appendCode = [stmt getString:7];
    dm.appendParams = [stmt getString:8];
    dm.appendResult = [stmt getString:9];
    
    dm.sender    = [User userWithId:dm.senderId];
    dm.recipient = [User userWithId:dm.recipientId];    
    
    [dm updateAttribute];

    return dm;
}


#pragma mark - setter & getter

- (NSString*) askId
{
    if ( [kDMCodeAskCard compare:appendCode] == NSOrderedSame ) {
        if ( [appendParams length] > 0 ) {
            NSObject* obj = [appendParams JSONValue];
            if ( [obj isKindOfClass:[NSDictionary class]] ) {
                NSDictionary* dic = (NSDictionary*) obj;
                id i = [dic objectForKey:@"askId"];
                if ( i == nil || i==[NSNull null]) {
                    return @"";
                }
                else {
                    return (NSString*)i;
                }
            }
            else {
                return @"";
            }
        }
        else {
            return @"";
        }
    }
    else {
        return @"";
    }
}


#pragma mark - 数据库操作方法

+ (int)restore:(sqlite_int64)userId messageArray:(NSMutableArray*)array all:(BOOL)all
{
	sqlite3* db = [DBConnection getDatabase];
    char *sql = "SELECT * FROM direct_messages where sender_id = ? or recipient_id = ? GROUP BY sender_id, recipient_id ORDER by created_at DESC LIMIT ?";

    Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
	[stmt bindInt64:userId forIndex:1];
	[stmt bindInt64:userId forIndex:2];
    [stmt bindInt32:all ? 200 : 20 forIndex:3];
   
    int count = 0;
    
    NSMutableDictionary* dic = [NSMutableDictionary dictionary];
    
    while ([stmt step] == SQLITE_ROW) {
        DirectMessage *dm = [DirectMessage initWithStatement:stmt];
        
        NSString* key = [NSString stringWithFormat:@"%lld,%lld", dm.recipientId, dm.senderId];
        NSLog(@"key=%@", key);
        if ( [dic objectForKey:key] == nil ) {
            [array addObject:dm];
            ++count;
            
            NSString* key = [NSString stringWithFormat:@"%lld,%lld", dm.senderId, dm.recipientId];
            [dic setObject:@"" forKey:key];
        }
        [dm release];
    }
	
	[stmt release];

    return count;
}


- (int)getConversation:(NSMutableArray*)messages
{
	
	sqlite3* db = [DBConnection getDatabase];
    char *sql = "SELECT * FROM direct_messages WHERE (sender_id = ? and recipient_id = ?) or (sender_id = ? and recipient_id = ?) ORDER BY created_at DESC LIMIT ? OFFSET ?";

	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt64:senderId                forIndex:1];
    [stmt bindInt64:recipientId             forIndex:2];
    [stmt bindInt64:recipientId             forIndex:3];
    [stmt bindInt64:senderId                forIndex:4];
    [stmt bindInt32:NUM_MESSAGE_PER_PAGE    forIndex:5];
    [stmt bindInt32:[messages count]        forIndex:6];
    
    int count = 0;
    while ([stmt step] == SQLITE_ROW) {
        DirectMessage *dm = [DirectMessage initWithStatement:stmt];
        [messages insertObject:dm atIndex:0];
        ++count;
        [dm release];
    }

	[stmt release];
    return count;
}


+ (BOOL)isExists:(sqlite_int64)anId
{
	sqlite3* db = [DBConnection getDatabase];
    char* sql = "select count(*) from direct_messages";
    Statement* stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt step];
    int rows = [stmt getInt32:0];
    NSLog(@"rows=%d", rows);
    [stmt release];
    
	sql = "SELECT id FROM direct_messages WHERE id=?";
	
	stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt64:anId forIndex:1];
	
    BOOL result = ([stmt step] == SQLITE_ROW) ? true : false;
    [stmt release];
    return result;
}


+ (int)countMessages:(int)userId
{
	sqlite3* db = [DBConnection getDatabase];
	char* sql = "SELECT count(*) FROM direct_messages WHERE sender_id = ?";

	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt64:userId forIndex:1];
    
    int ret = 0;
    
    if ([stmt step] == SQLITE_ROW) {
        ret = [stmt getInt32:0];        
    }
	
	[stmt release];
    return ret;
}


+ (sqlite_int64)lastSentMessageId
{
	sqlite3* db = [DBConnection getDatabase];
	char* sql = "SELECT id FROM direct_messages WHERE sender_screen_name = ? ORDER BY created_at DESC LIMIT 1";
	
	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindString:[GuaziAppDelegate getAppDelegate].user.screenName forIndex:1];
    
    sqlite_int64 ret = 0;
    if ([stmt step] == SQLITE_ROW) {
        ret = [stmt getInt64:0];
    }
	
	[stmt release];
    return ret;
}


+ (DirectMessage*) lastSendMessage
{
	sqlite3* db = [DBConnection getDatabase];
	char* sql = "SELECT * FROM direct_messages WHERE sender_screen_name = ? ORDER BY created_at DESC LIMIT 1";
	
	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindString:[GuaziAppDelegate getAppDelegate].user.screenName forIndex:1];
    
    DirectMessage* ret = nil;
    if ([stmt step] == SQLITE_ROW) {
        ret = [[[DirectMessage alloc] initWithStatement:stmt] autorelease];
    }
	
	[stmt release];
    return ret;
}

- (void)insertDB
{
	sqlite3* db = [DBConnection getDatabase];
	char* sql = "INSERT INTO direct_messages VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt64:tweetId             forIndex:1];
    [stmt bindInt64:user.userId         forIndex:2];
    [stmt bindInt64:recipient.userId    forIndex:3];
    
    [stmt bindString:text               forIndex:4];
    [stmt bindInt32:createdAt           forIndex:5];
    [stmt bindString:user.screenName    forIndex:6];
    [stmt bindString:recipient.screenName forIndex:7];
    
    self.appendCode = @"";
    self.appendParams = @"";
    self.appendResult = @"";
    
    [stmt bindString:appendCode forIndex:8];
    [stmt bindString:appendParams forIndex:9];
    [stmt bindString:appendResult forIndex:10];
    
    if ([stmt step] != SQLITE_DONE) {
		[GuaziAppDelegate showAlert:@"数据库访问错误！DirectMessage.insertDB"];
        [stmt release];
		NSAssert2( 0, @"Fail to prepare statement: %s (%s)", sql, sqlite3_errmsg(db) );
    }
	
    [stmt release];
    
    // Update user and followee record
    [user updateDB:YES withName:NO withAccount:NO];
    [recipient updateDB:YES withName:NO withAccount:NO];

    // Add user to followee database
    [Followee insertDB:user];
}

- (void)deleteFromDB
{
	sqlite3* db = [DBConnection getDatabase];
	char* sql = "DELETE FROM direct_messages WHERE id = ?";

	Statement *stmt = [[Statement alloc] initWithDB:db sql:sql];
    [stmt bindInt64:tweetId forIndex:1];
    [stmt step];    // ignore error
    [stmt release];
}

@end
